package com.iron.visual.admin.notify;

import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 自定义 SmsNotifer 监控事件
 *
 * @author YT
 * @date 2019-07-11
 */
@Slf4j
@Data
@EqualsAndHashCode(callSuper = false)
public class SmsNotifier extends AbstractStatusChangeNotifier {

    private String[] phones = {"12345678901"};

    private static final String DEFAULT_MESSAGE = "#{application.name} (#{application.id})\\nstatus changed from #{from.status} to #{to.status}\\n\\n#{application.healthUrl}";

    private String[] ignoreChanges = new String[]{"UNKNOWN:UP"};

    private final SpelExpressionParser parser = new SpelExpressionParser();

    private String title = "服务告警";

    private Expression message;

    public SmsNotifier(InstanceRepository repository) {
        super(repository);
        this.message = parser.parseExpression(DEFAULT_MESSAGE, ParserContext.TEMPLATE_EXPRESSION);
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent instanceEvent, Instance instance) {
        log.info("自定义服务状态改变时，监控信息通知执行");
        Map<String, String> map = this.createMessage(instanceEvent,instance);
        return Mono.fromRunnable(() -> log.info(DEFAULT_MESSAGE));
    }

    /**
     * 消息体信息
     *
     * @return
     */
    private Map<String, String> createMessage(InstanceEvent instanceEvent, Instance instance) {
        Map<String, String> messageJson = new HashMap<>();
        messageJson.put("text", this.getMessage(instanceEvent,instance));
        messageJson.put("title", this.title);
        return messageJson;
    }

    private String getMessage(InstanceEvent instanceEvent, Instance instance) {
        Map<String, Object> messageString = new HashMap<>();
        messageString.put("event", instanceEvent);
        messageString.put("instance", instance);
        messageString.put("lastStatus", getLastStatus(instanceEvent.getInstance()));
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.addPropertyAccessor(new MapAccessor());
        return message.getValue(context, String.class);
    }
}
